require "http/client"
require "openssl/hmac"
require "base64"
require "uuid"
require "uri"
require "./config"

class Sender

  def self.dy_params(mobile : String, code : String)
    h = { "SignatureMethod" => "HMAC-SHA1",
          "SignatureNonce" => UUID.random().to_s,
          "AccessKeyId" => Config.env["access_key"],
          "SignatureVersion" => "1.0",
          "Timestamp" => Time.utc_now.to_s("%Y-%m-%dT%H:%M:%SZ"),
          "Format" => "JSON",
          "Action" => "SendSms",
          "Version" => "2017-05-25",
          "RegionId" => "cn-hangzhou",
          "PhoneNumbers" => mobile,
          "SignName" => Config.env["sms_sign_name"],
          "TemplateParam" => %({"code":"#{code}"}),
          "TemplateCode" => Config.env["sms_template"]}
    h
  end

  def self.escape(value : String)
    URI.escape(value).gsub("\+", "%20").gsub("\*", "%2A").gsub("%7E", "~")
  end

  def self.param_string(params : Hash(String, String))
    params.to_a.sort.map { |x| "#{x[0]}=#{escape(x[1])}"}.reduce {|acc, x| "#{acc}&#{x}"}
  end

  def self.string_to_sign(parastr : String)
    a = escape("/")
    "GET&#{a}&#{escape(parastr)}"
  end

  def self.sign(secret : String, str_to_sign : String)
    escape(Base64.strict_encode(OpenSSL::HMAC.digest(:sha1, "#{secret}&", str_to_sign)))
  end

  def self.send(mobile : String, code : String)
    params = dy_params(mobile, code)
    parastr = param_string(params)
    to_sign = string_to_sign(parastr)
    signed = sign(Config.env["access_secret"], to_sign)
    response = HTTP::Client.get "http://dysmsapi.aliyuncs.com/?Signature=#{signed}&#{parastr}"
    if response.success?
      ret_params = JSON.parse response.body
      if ret_params["Code"] == "OK"
        [1, "OK"]
      else
        [0, "Message"]
      end
    else
      [0, "失败001"]
    end
  end
end
